package com.oazon.voicelib.service;

import android.content.Context;
import android.os.Environment;
import android.util.Log;

import com.iflytek.cloud.InitListener;
import com.iflytek.cloud.RecognizerListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechRecognizer;
import com.iflytek.cloud.SpeechSynthesizer;
import com.iflytek.cloud.SpeechUnderstander;
import com.iflytek.cloud.SpeechUnderstanderListener;
import com.iflytek.cloud.SpeechUtility;
import com.iflytek.cloud.SynthesizerListener;
import com.iflytek.cloud.VoiceWakeuper;
import com.iflytek.cloud.WakeuperListener;
import com.iflytek.cloud.util.ResourceUtil;
import com.iflytek.cloud.util.ResourceUtil.RESOURCE_TYPE;

public class SpeechUtil {
	private Context context;
	// 听写识别
	private SpeechRecognizer mIat;
	// 唤醒
	private VoiceWakeuper mIvw;
	private static final String APPID = "554ae798";
	private String resPath;
	// 唤醒门阙值，-20为最小，60最大
	private int curThresh = -9;
	// 语义识别
	private SpeechUnderstander mSpeechUnderstander;
	// 语音合成
	private SpeechSynthesizer mTts;
	// 说话声音对象
	private String voicerCloud = "xiaoyan";

	public SpeechUtil(Context context) {
		this.context = context;
		// 初始化Speech对象，建议在最开始的时候使用
		SpeechUtility
				.createUtility(context, SpeechConstant.APPID + "=" + APPID);
		// resPath是语音唤醒词目录路径assets/ivw/APPID.jet
		resPath = ResourceUtil.generateResourcePath(context,RESOURCE_TYPE.assets, "ivw/" + APPID + ".jet");
		// 初始化唤醒
		initWake();
		// 初始化语义识别
		initUnderstand();
		// 初始化语义合成
		initTts();
		// 初始化语音听写
		initIat();
	}

	private InitListener initListener = new InitListener() {

		@Override
		public void onInit(int arg0) {
			// TODO Auto-generated method stub
			Log.d("OAZON", "初始化返回码" + arg0);
		}
	};
	
	public boolean isUnderstand(){
		return mSpeechUnderstander.isUnderstanding();
	}

	/**
	 * Ĭ��ֻΪ��һ�����Ѵ���������Ϊ-20�� �����޸�ʹ��setParameter�����޸ģ� -20~60
	 * ���û���ҵ������ ������л���
	 */
	private void initWake() {
		try {
			StringBuffer param = new StringBuffer();
			param.append(ResourceUtil.IVW_RES_PATH + "=" + resPath);
			param.append("," + ResourceUtil.ENGINE_START + "="
					+ SpeechConstant.ENG_IVW);
			boolean ret = SpeechUtility.getUtility().setParameter(
					ResourceUtil.ENGINE_START, param.toString());
			if (!ret) {
				Log.d("OAZON", "������������ʧ�ܣ�");
				Log.d("OAZON", " initWake()");
			}
			// ��ʼ�����Ѷ���
			mIvw = VoiceWakeuper.createWakeuper(context, initListener);
			// ��ղ���
			mIvw.setParameter(SpeechConstant.PARAMS, null);
			// ��������ֵ�������ԴЯ��Ļ��Ѵʸ����ա�id:����;id:���ޡ��ĸ�ʽ����
			mIvw.setParameter(SpeechConstant.IVW_THRESHOLD, "0:" + curThresh);
			// ���û���ģʽ
			mIvw.setParameter(SpeechConstant.IVW_SST, "wakeup");
			// ���ó�����л���
			mIvw.setParameter(SpeechConstant.KEEP_ALIVE, "1");
		} catch (Exception e) {
			e.printStackTrace();
		}
	
	}

	/**
	 * 
	 * @param listener
	 * @return
	 */
	public boolean startWake(WakeuperListener listener) {
		boolean flag = false;
		
		mIvw = VoiceWakeuper.getWakeuper();
		if (mIvw == null) {
			initWake();
		}
		if (mIvw != null) {
			mIvw.startListening(listener);
			flag = true;
		} else {
			// ����δ��ʼ��;
			Log.d("OAZON", "����δ��ʼ��");
			Log.d("OAZON", "startWake(WakeuperListener listener)");
		}
		return flag;
	}

	/**
	 * ���Ѳ������ã�key�����õĲ����У� SpeechConstant.IVW_SST:����orѵ��
	 * SpeechConstant.KEEP_ALIVE:�Ƿ񱣳ֻ���
	 * SpeechConstant.IVW_WORD_PATH:ѵ�����ϲ�����ɵ���Դ·��
	 * SpeechConstant.IVW_THRESHOLD:��������ֵ
	 * 
	 * @param key
	 *            - �������
	 * @param value
	 *            - ����ֵ
	 * @return true ���óɹ�����������ʧ��
	 */
	public boolean setWakeParameter(String key, String value) {
		boolean flag = false;
		if (mIvw != null) {
			flag = mIvw.setParameter(key, value);
		}
		return flag;
	}

	/**
	 * �رջ���
	 */
	public void stopWake() {
		if (mIvw.isListening())
			mIvw.stopListening();
	}

	/**
	 * ��ٻ���
	 */
	public void destroyWake() {
		mIvw = VoiceWakeuper.getWakeuper();
		if (mIvw != null) {
			mIvw.destroy();
		}
	}

	/**
	 * Ĭ�������Ĺ��� ����ǰ�˳�ʱ4�� ������˳�ʱ1�� �б����
	 * ��Ƶ����·��/mnt/sdcard/iflytek/wavaudio.pcm
	 */
	private void initUnderstand() {
		// �����������ʶ�����ڶ��������ǳ�ʼ�������ߡ��жϳ�ʼ���ɹ���ʧ��
		mSpeechUnderstander = SpeechUnderstander.createUnderstander(context,
				initListener);
		// ��������
		mSpeechUnderstander.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
		// ������������ mandarin����
		mSpeechUnderstander.setParameter(SpeechConstant.ACCENT, "mandarin");
		// ��������ǰ�˵�
		mSpeechUnderstander.setParameter(SpeechConstant.VAD_BOS, "4000");
		// ����������˵�
		mSpeechUnderstander.setParameter(SpeechConstant.VAD_EOS, "1000");
		// �����Ƿ��б����
		mSpeechUnderstander.setParameter(SpeechConstant.ASR_PTT, "1");
		// ������Ƶ����·��
		mSpeechUnderstander.setParameter(SpeechConstant.ASR_AUDIO_PATH,
				Environment.getExternalStorageDirectory()
						+ "/iflytek/wavaudio.pcm");
	}

	/**
	 * 语义识别参数设置，
	 * key可设置的参数有：
	 * SpeechConstant.NET_TIMEOUT:网络连接超时时间
	 * SpeechConstant.KEY_SPEECH_TIMEOUT:语音输入超时时间 
	 * SpeechConstant.LANGUAGE:语言
	 * SpeechConstant.ACCENT:语言区域
	 * SpeechConstant.DOMAIN:应用领域
	 * SpeechConstant.AUDIO_SOURCE:音频源
	 * SpeechConstant.VAD_BOS:前端点超时
	 * SpeechConstant.VAD_EOS:后端点超时
	 * SpeechConstant.SAMPLE_RATE:识别采样率
	 * SpeechConstant.ASR_PTT:设置是否有标点符号
	 * SpeechConstant.RESULT_TYPE:识别结果类型
	 * SpeechConstant.SEARCH_AREA:地图搜索设置区域 
	 * SpeechConstant.ASR_AUDIO_PATH识别录音保存路径
	 *@param 参数：
	 *			 key - 参数名称   value - 参数值 
	 *@return 返回： true 设置成功，否则设置失败
	 */
	public boolean setUnderstanderParameter(String key, String value) {
		boolean flag = false;
		if (mSpeechUnderstander != null) {
			flag = mSpeechUnderstander.setParameter(key, value);
		}
		return flag;
	}

	/**
	 * 
	 * @param listener
	 *            - ����ʶ��ص�������
	 * @return ������� 0Ϊ��ȷ.��ȷʱ��ʾ��ʼ˵��
	 */
	public int startUnderstandSpeech(SpeechUnderstanderListener listener) {
		int ret = -1;
		// ��ʼǰ���״̬
		mSpeechUnderstander = SpeechUnderstander.getUnderstander();
		if (mSpeechUnderstander == null) {
			initUnderstand();
		}
		if (mSpeechUnderstander.isUnderstanding()) {
			mSpeechUnderstander.stopUnderstanding();
		}
		ret = mSpeechUnderstander.startUnderstanding(listener);
		return ret;
	}

	/**
	 * ֹͣ¼��
	 */
	public void stopSpeechUnderstander() {
		mSpeechUnderstander.stopUnderstanding();
		mSpeechUnderstander.cancel();
	}

	/**
	 * ��ٻ���
	 */
	public void destroyUnderstander() {
		mSpeechUnderstander = SpeechUnderstander.getUnderstander();
		if (mSpeechUnderstander != null) {
			mSpeechUnderstander.destroy();
		}
	}

	/**
	 * Ĭ���ƶ����� ������ΪС�� ����50 ����50 ����50 ��������Ƶ������ 3
	 */
	private void initTts() {
		// ��ʼ���ϳɶ���
		mTts = SpeechSynthesizer.createSynthesizer(context, initListener);
		// ��ղ���
		mTts.setParameter(SpeechConstant.PARAMS, null);

		// ����ʹ���ƶ�����
		mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
		// ���÷�����
		mTts.setParameter(SpeechConstant.VOICE_NAME, voicerCloud);

		// ��������
		mTts.setParameter(SpeechConstant.SPEED, "50");

		// ��������
		mTts.setParameter(SpeechConstant.PITCH, "50");

		// ��������
		mTts.setParameter(SpeechConstant.VOLUME, "50");

		// ���ò�������Ƶ������
		mTts.setParameter(SpeechConstant.STREAM_TYPE, "3");
	}

	/**
	 * ʶ��ϳ����ã�key�����õĲ����У� SpeechConstant.VOICE_NAME:����������
	 * SpeechConstant.SPEED:���� SpeechConstant.VOLUME:�ϳɵ�����
	 * SpeechConstant.PITCH:��� SpeechConstant.BACKGROUND_SOUND: ��������
	 * SpeechConstant.TTS_BUFFER_TIME:�ϳ���Ƶ����ʱ��
	 * SpeechConstant.STREAM_TYPE:��������
	 * SpeechConstant.KEY_REQUEST_FOCUS:�����Ƿ�Ự�������ͣ��̨���ֲ���
	 * SpeechConstant.TTS_AUDIO_PATH:�ϳ�¼������·��
	 * SpeechConstant.SAMPLE_RATE:�ϳɲ�����
	 * 
	 * @param key
	 *            - �������
	 * @param value
	 *            - ����ֵ
	 * @return true ���óɹ�����������ʧ��
	 */
	public boolean setTtsParameter(String key, String value) {
		boolean flag = false;
		if (mTts != null) {
			flag = mTts.setParameter(key, value);
		}
		return flag;
	}

	/**
	 * ��ʼ�����ϳ�
	 * 
	 * @param text
	 *            -�ϳɵ�����
	 * @param listener
	 *            - �����ϳɻص�������
	 * @return
	 */
	public int startSpeechSynthesizer(String text, SynthesizerListener listener) {
		mTts = SpeechSynthesizer.getSynthesizer();
		if (mTts == null) {
			initTts();
		}
		int code = mTts.startSpeaking(text, listener);
		return code;
//		return 1;
	}

	/**
	 * ��������ϳ�
	 */
	public void destroyTts() {
		mTts = SpeechSynthesizer.getSynthesizer();
		if (mTts != null) {
			mTts.destroy();
		}
	}

	/**
	 * Ĭ�������Ĺ��� ����ǰ�˳�ʱ4�� ������˳�ʱ1�� �б����
	 * ��Ƶ����·��/mnt/sdcard/iflytek/wavaudio.pcm
	 */
	private void initIat() {
		// ��ʼ��ʶ�����
		mIat = SpeechRecognizer.createRecognizer(context, initListener);
		// ��������
		mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
		// ������������ mandarin����
		mIat.setParameter(SpeechConstant.ACCENT, "mandarin");
		// ��������ǰ�˵�
		mIat.setParameter(SpeechConstant.VAD_BOS, "4000");
		// ����������˵�
		mIat.setParameter(SpeechConstant.VAD_EOS, "1000");
		// �����Ƿ��б����
		mIat.setParameter(SpeechConstant.ASR_PTT, "1");
		// ������Ƶ����·��
		mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,
				Environment.getExternalStorageDirectory()
						+ "/iflytek/wavaudio.pcm");
	}

	public void startIat(RecognizerListener listener) {

		// ��ʼǰ���״̬
		mIat = SpeechRecognizer.getRecognizer();
		if (mIat == null) {
			initUnderstand();
		} else {
			mIat.startListening(listener);
		}
	}

	public void stopSeechSynthesizer(){
		if(mTts.isSpeaking()){
			mTts.stopSpeaking();
		}
	}
}
